﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using StripeOne.Core.S1Tools;
using StripeOne.Web.Core.Common;
using StripeOne.Core.S1Cache;
using StripeOne.Core.XmlConfig;
using StripeOne.Core.S1Log;

namespace StripeOne.Web.Core.Configuration
{
    public class StripeOneInstances : XmlConfig
    {
        public StripeOneInstances() : this("default") { }
        public StripeOneInstances(string section)
            : base("Instances.s1config", section, "instances", "instance")
        {
            this.CacheTime = 0;
        }

        public override int Id
        {
            get { return this.GetString("id", this.GetXmlAttributeValue("id")).ToInt32(); }
        }

        public int GMT
        {
            get { return this.GetString("gmt", this.GetXmlAttributeValue("gmt")).ToInt32(); }
        }

        public string CssPathFile
        {
            get { return this.GetString("cssPathFile", this.GetXmlAttributeValue("cssPathFile")); }
        }

        private List<Domain> _domains;
        private List<Domain> Domains
        {
            get
            {
                if (this._domains == null)
                {
                    this._domains = this.GetXmlObjects<Domain>("domains", "domain");
                }
                return this._domains;
            }
        }

        private Domain _currentDomain;
        public Domain CurrentDomain
        {
            get
            {
                string url = GeneralTools.RemoveEndSlash(GetCurrentHost());

                if (this._currentDomain == null)
                    this._currentDomain = new Domain();
                else if (!_currentDomain.Equals(url))
                {
                    Domain tempDomain = StripeOneInstances.Current.Domains.Find(i => url.ToLower().Equals(i.DomainAddress.ToLower()));
                    if (tempDomain != null)
                        this._currentDomain = tempDomain;
                }
                return this._currentDomain;
            }
            set { this._currentDomain = value; }
        }

        private LanguageXml _language;
        public LanguageXml Language
        {
            get
            {
                if (this._language == null)
                {
                    this._language = this.GetXmlConfig<LanguageXml>("language");
                }
                return this._language;
            }
        }

        public static StripeOneInstances Current
        {
            get
            {
                string cacheKey = Extensions.ToCacheKeyFormat("VIDEOSTORE_INSTANCE_CACHEKEY_" + GetCurrentHost());
                object obj = S1Cache.GetObject(cacheKey);
                if (obj != null && obj is StripeOneInstances)
                {
                    return (StripeOneInstances)obj;
                }
                StripeOneInstances instance = GetCurrentNoCache();
                instance.Default = StripeOneInstances.DefaultInstance;
                S1Cache.Add(instance, cacheKey, 0);

                return instance;
            }
        }

        public static StripeOneInstances DefaultInstance
        {
            get
            {
                string cacheKey = "VIDEOSTORE_DEFAULT_INSTANCE_CACHEKEY";
                object obj = S1Cache.GetObject(cacheKey);
                if (obj != null && obj is StripeOneInstances)
                {
                    return (StripeOneInstances)obj;
                }
                StripeOneInstances instance = Instances.Find(i => i.IsDefault);
                if (instance == null)
                {
                    instance = new StripeOneInstances();
                }
                S1Cache.Add(instance, cacheKey, 0);
                return instance;
            }
        }

        private static StripeOneInstances GetCurrentNoCache()
        {
            Domain domain = null;
            List<StripeOneInstances> instances = StripeOneInstances.Instances;

            StripeOneInstances instDefault = instances.FirstOrDefault(i => i.IsDefault);
            try
            {
                string url = GeneralTools.RemoveEndSlash(HttpContext.Current.Request.Url.Host);

                foreach (StripeOneInstances instance in instances)
                {
                    domain = instance.Domains.Find(i => url.ToLower().Equals(i.DomainAddress.ToLower()));
                    if (domain != null)
                    {
                        S1Log.Default.Log("Host find SUCCESS, Set Domain from host: " + url);
                        return StripeOneInstances.SetDomain(instance, domain);
                    }
                }
                if (instDefault != null)
                {
                    S1Log.Default.Error("WARNING! Host: " + url + " not find in InstancesConfig, using first Domain from Default Instance.");
                    return StripeOneInstances.SetDomain(instDefault, instDefault.Domains.FirstOrDefault());
                }
                else
                {
                    S1Log.Default.Error("Get Instance error - check Instances.s1config");
                    return StripeOneInstances.SetDomain(new StripeOneInstances(), new Domain());
                }
            }
            catch (Exception ex)
            {
                S1Log.Default.Exception(ex);
                if (instDefault != null)
                {
                    return StripeOneInstances.SetDomain(instDefault, instDefault.Domains[0]);
                }
                else
                {
                    S1Log.Default.Error("Get Instance error - check Instances.s1config");
                    return StripeOneInstances.SetDomain(new StripeOneInstances(), new Domain());
                }
            }
        }

        public static List<StripeOneInstances> Instances
        {
            get
            {
                return S1Cache.AutoCache<List<StripeOneInstances>>("STRIPEONE_INSTANCESCONFIG_INSTANCES", 100, () => GetInstancesNoCache());
            }
        }

        private static List<StripeOneInstances> GetInstancesNoCache()
        {
            try
            {
                return XmlObjectTool.GetXmlObjects<StripeOneInstances>(GeneralTools.GetConfigFolderPath() + "Instances.s1config", "instances", "instance", true, 0);
            }
            catch (Exception e)
            {
                S1Log.Default.Exception(e);
                return new List<StripeOneInstances>();
            }
        }

        private static StripeOneInstances SetDomain(StripeOneInstances instance, Domain domain)
        {
            if (instance == null)
            {
                S1Log.Default.Error("SetDomain: Instace is null, check!");
                instance = new StripeOneInstances();
            }
            if (domain == null)
            {
                S1Log.Default.Error("SetDomain: Domain is null, check!");
                domain = new Domain();
            }

            S1Log.Default.Log("SetDomain, DomainAddress: " + domain.DomainAddress);
            instance.CurrentDomain = domain;
            return instance;
        }

        public static string GetCurrentHost()
        {
            string host = String.Empty;
            try
            {
                host = HttpContext.Current.Request.Url.Host;
            }
            catch { }
            return host;
        }
    }

    #region Language class

    public class LanguageXml : XmlConfig
    {
        public LanguageXml() : base("language") { }
        public LanguageXml(string section) : base(section) { }

        public override int Id
        {
            get { return this.GetString("id", this.GetXmlAttributeValue("id")).ToInt32(); }
        }

        public string CultureName
        {
            get { return this.GetString("culture_info", this.GetXmlAttributeValue("culture_info")); }
        }

        public string Partials
        {
            get { return this.GetString("partials", this.GetXmlAttributeValue("partials")); }
        }

        private System.Globalization.CultureInfo _cultureInfo;
        public System.Globalization.CultureInfo CultureInfo
        {
            get
            {
                if (_cultureInfo == null)
                {
                    try
                    {
                        _cultureInfo = new System.Globalization.CultureInfo(this.CultureName);
                        _cultureInfo.NumberFormat.CurrencyDecimalDigits = this.CurrencyDecimalPrecision;
                        _cultureInfo.NumberFormat.CurrencyDecimalSeparator = this.CurrencyDecimalSeparator;
                        _cultureInfo.NumberFormat.CurrencySymbol = this.CurrencySymbol == "none" ? string.Empty : this.CurrencySymbol;

                        if (this.ShowCurrencyGroupSeparator)
                            _cultureInfo.NumberFormat.CurrencyGroupSeparator = this.CurrencyGroupSeparator;
                        else
                            _cultureInfo.NumberFormat.CurrencyGroupSeparator = string.Empty;

                    }
                    catch (Exception e)
                    {
                        S1Log.Default.Exception(e);
                        _cultureInfo = new System.Globalization.CultureInfo("pt-BR");
                    }
                }
                return _cultureInfo;
            }
        }

        public string DateTimeFormatShort
        {
            get
            {
                return this.GetString("datetime_format_short", this.GetXmlAttributeValue("datetime_format_short", "dd/MM/yyyy às HH:mm"));
            }
        }

        public string DateTimeFormatLong
        {
            get
            {
                return this.GetString("datetime_format_long", this.GetXmlAttributeValue("datetime_format_long", "dddd, dd/MM/yyyy às HH:mm"));
            }
        }

        public string DateTimeFormatFeed
        {
            get
            {
                return this.GetString("datetime_format_feed", this.GetXmlAttributeValue("datetime_format_feed", "dd/MM/yyyy HH:mm"));
            }
        }

        public string TranslationLanguage
        {
            get
            {
                return this.GetString("translation");
            }
        }

        public string PageLang
        {
            get
            {
                return this.GetString("pageLang");
            }
        }

        public string PageCountry
        {
            get
            {
                return this.GetString("pageCountry");
            }
        }

        public string CurrencyDecimalSeparator
        {
            get
            {
                return this.GetString("currencyDecimalSeparator", ",");
            }
        }

        public string CurrencyGroupSeparator
        {
            get
            {
                return this.GetString("currencyGroupSeparator", "");
            }
        }

        public int CurrencyDecimalPrecision
        {
            get
            {
                return this.GetInt32("currencyDecimalPrecision", 2);
            }
        }

        public string CurrencySymbol
        {
            get
            {
                return this.GetString("currencySymbol", "");
            }
        }

        public bool ShowCurrencyGroupSeparator
        {
            get
            {
                return this.GetBoolean("showCurrencyGroupSeparator", true);
            }
        }
    }
    
    #endregion

    #region Domain class

    public class Domain : XmlConfig
    {
        public Domain() : this("domain") { }
        public Domain(string section) : base(section) { }

        public string DomainAddress
        {
            get { return this.GetXmlAttributeValue("domain", "feDomain"); }
        }

        public string StripeOneConfigSection
        {
            get { return this.GetXmlAttributeValue("domain", "stripeOneConfigSection").Length > 0 ? this.GetXmlAttributeValue("domain", "stripeOneConfigSection") : "default"; }
        }
    }

    #endregion
}